﻿/// <reference path="_namespace.js" />
/// <reference path="../BaseObject.js" />

/*****************************************************************************
Ajax library class definition. Kevin Robinson 2006.
Class: ajax.events.EventRouter
/*****************************************************************************/


$addNamespace("ajax.events");

//-----------------------------------------------------------------------------
ajax.events.EventRouter = function(wind, el, eventType) // Constructor
{               
    this.window     = wind;
    this.lsnrs      = new Array();
    this.el         = el;
    this.sender     = el;
    this.eventType  = eventType;
    this.returnFalse= false;

    // Not sure we need this now...this *could be* an array...
    // so we store an array of eventRouters on an object, which could be picked through by external
    // Code, each router having its own event type.
    if (typeof(el.eventRouters) == "undefined")
        el.eventRouters = new Array();
    el.eventRouters[el.eventRouters.length] = this;    
    
      
    //Create a closure of this event router so that any time the event fires
    // We can always get a handle to ourselves, thus no need to store against the element itself    
    // Thus no restriction on only one event router (and ergo event) per object.
    var self = this;
    
    // this would resolve to el['onmouseover'] = doSomething
    // or, rather el.onmouseover = doSomething. Clever.
    el[eventType]   = function(event)
    { 
        // this = the thing that generated the event
        
        // Get a handle to this eventrouter
        var router = self;
            
        // "event" is either undefined (IE) or the event object 
        // "this" = the DOM object that fired the event 
        var e = event || router.window.event || {};
        
        // and call our notify method in a neuteral context
        router.notify(e); 
        
        // are we to stop event bubbling?
        if (router.returnFalse == true)
        {
            if (e)
                e.canceBubble = true;
            return false;
        }                   
    };     
}

//-----------------------------------------------------------------------------
ajax.lang.extend("ajax.events.EventRouter", "ajax.BaseObject"); // Inherit
if ($getDesignMode())
    ajax.events.EventRouter.prototype = ajax.BaseObject.prototype;

//-----------------------------------------------------------------------------
ajax.events.EventRouter.prototype =
{
    addListener: function(functionPointer)
    {///<summary>Add the function pointer (unless already added) as a listener to this event.</summary>
        this.lsnrs.append(functionPointer, true);  // No duplicates!
    },
    
    removeListener: function(functionPointer)
    {///<summary>Removes the listener handler (if exists) from this event.</summary>
        this.lsnrs.remove(functionPointer); // Just remove it (if exists)
    },
    
    getListeners: function()
    {///<summary>Returns an array of listener objects for this event.</summary>
     ///<returns type="Array"/>
        return this.lsnrs;
    },
    
    notify: function(e)
    {///<summary>Fires the event to all listeners.</summary>
        // because we are called in context (router.notify(e) "this" is the EventRouter object 
        // Get a handle to our event list
        var lsnrs = this.lsnrs;
        // Loop through and call each one in turn, while each event handler does not finish
        // "return false"
        var cancelled = false;
        for (var i = 0; i < lsnrs.length; i++)
        {            
            if (!cancelled)
            {
                var lsnr = lsnrs[i];
                // And CALL it, passing this event router's element as context
                var ret = lsnr.call(this.el, e, this);                
                if (false == ret)
                    cancelled = true;
            }          
            else
                break;
        }
    },
    
    getSender: function()
    {///<summary>Returns the sender / originator of this event.</summary>
     ///<returns type="Object"/>
        return this.sender;
    }    
}

//-----------------------------------------------------------------------------
// Static method to get the event of an object 
ajax.events.EventRouter.getEvent = function(wind, obj, eventType)
{
    var sCompareName = eventType.toLowerCase();    
    
    // Get the event router for the specified event if it exists
    var sType = typeof(obj.eventRouters);
    
    if (sType == "unknown")
    {
        ajax.debug.Output.writeLn("Events issue, type is " + sType + " so unable to attach " + eventType + " listener");
        return null;
    }
    
    if ( sType != "undefined" )
    {   
        // Seems a router already exists for this object...
        try
        {                 
            var routers = obj.eventRouters;
            for (var i = 0; i < routers.length; i++)
            {
                var router = routers[i];
                /*
                 if (sCompareName == router.eventType.toLowerCase() && wind === router.window)    
                 NOTE: We no longer test that the window is the same object as the one attached to the router
                 // because if it ISN'T then we'd wipe out the existing, valid event handler
                 which could have *VERY* bad consequences!. In any case, perhaps the ie window.event args are
                 passed around the different window objects...?
                */
                if (sCompareName == router.eventType.toLowerCase())                                    
                    return router;
            }
        }
        catch(ex)
        {            
            ajax.debug.Output.writeLn("Events issue: " + obj + " had eventRouters but was invalid despite type " + sType);
        }
    }
    
    // Otherwise create new        
    var newRouter = ajax.lang.safeNew("ajax.events.EventRouter", wind, obj, eventType);        
    return newRouter;
}

//-----------------------------------------------------------------------------
ajax.events.EventRouter.prototype.toString = function()
{
    return "ajax.events.EventRouter";
}

//-----------------------------------------------------------------------------
ajax.events.EventRouter.prototype.toClassName = function()
{
    return ajax.lang.getClassName("ajax.events.EventRouter");
}


//-----------------------------------------------------------------------------
// Statics
ajax.events.EventRouter.cast = function(obj)
{///<returns type="ajax.events.EventRouter"/>
    return obj;
}